package com.cmas.platform.utils;

import com.aidex.common.core.redis.RedisCache;
import com.aidex.common.utils.ObjectUtils;
import com.aidex.common.utils.StringUtils;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.cmas.platform.cache.LoadData;
import com.cmas.platform.domain.Post;
import com.cmas.platform.domain.Region;
import com.cmas.platform.domain.Section;
import com.cmas.platform.dto.PostDto;
import com.cmas.platform.service.PostFullService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;


import java.util.*;

/**
 * @Author su
 * @Date 2023/5/2 20:24
 */
@Component
public class DataRedisUtil {
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private PostFullService postFullService;


    public void addRedisPost(String regionCode, String sectionCode, String postId) {
        if (StringUtils.isNotEmpty(postId)) {
            PostDto postDto = postFullService.getPost(postId);
            if (postDto != null) {
                //首页
                if (redisCache.hasKey(LoadData.POST_CODE + regionCode)) {
                    reloadRedisPostDtoList(LoadData.POST_CODE + regionCode, postDto, LoadData.POST_TIME);
                }
                //版块
                if (redisCache.hasKey(LoadData.POST_CODE + regionCode + "_" + sectionCode)) {
                    reloadRedisPostDtoList(LoadData.POST_CODE + regionCode + "_" +
                            sectionCode, postDto, LoadData.POST_SECTION_TIME);
                }
            }
        }
    }

    /**
     * 删除缓存帖子
     *
     * @param ids
     */

    @Async
    public void deleteRedisPost(List<String> ids) {
        List<PostDto> postDtoList = postFullService.selectPostFullDto(ids);
        Map<String, List<PostDto>> map = new HashMap<>();
        for (PostDto postDto : postDtoList) {
            List<PostDto> list = map.get(postDto.getRegionCode() + "_" + postDto.getSectionCode());
            if (ObjectUtils.isEmpty(list)) {
                list = new ArrayList<>();
            }
            list.add(postDto);
            map.put(postDto.getRegionCode() + "_" + postDto.getSectionCode(), list);
        }
        deleteRedisPost(map);
    }

    public void deleteRedisPost(Map<String, List<PostDto>> map) {
        Iterator<Map.Entry<String, List<PostDto>>> iterator = map.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, List<PostDto>> entry = iterator.next();
            List<PostDto> sectionPostList = ConvertUtil.castList(getRedisSectionPost(0,
                    Integer.MAX_VALUE, entry.getKey()), PostDto.class);
            String regionCode = entry.getKey().split("_")[0];
            List<PostDto> indexPostList = ConvertUtil.castList(getRedisSectionPost(0,
                    Integer.MAX_VALUE, regionCode), PostDto.class);
            for (PostDto postDto : entry.getValue()) {
                sectionPostList.removeIf(item -> item.getId().equals(postDto.getId()));
                indexPostList.removeIf(item -> item.getId().equals(postDto.getId()));
            }
            //版块
            reloadRedisPostDtoList(LoadData.POST_CODE + entry.getKey(), sectionPostList, LoadData.POST_SECTION_TIME);
            //首页
            reloadRedisPostDtoList(LoadData.POST_CODE + regionCode, indexPostList, LoadData.POST_TIME);
        }
    }


    public void reloadRedisPostDtoList(String key, PostDto postDto, long time) {
        List<PostDto> redisPostDtoList = ConvertUtil.castList(redisCache
                .lGet(key, 0, -1), PostDto.class);
        int index = getIndex(postDto, redisPostDtoList);
        if (index != -1) {
            redisPostDtoList.set(index, postDto);
        } else {
            redisPostDtoList.add(postDto);
            redisPostDtoList.stream()
                    .sorted(Comparator.comparing(PostDto::getCreateTime).reversed());
        }
        redisCache.deleteKey(key);
        redisCache.listRightPushAll(key, Arrays.asList(redisPostDtoList.toArray()), time);
    }


    public void reloadRedisPostDtoList(String key, List<PostDto> postDtoList, long time) {
        postDtoList.stream().sorted(Comparator
                .comparing(PostDto::getCreateTime).reversed());
        redisCache.deleteKey(key);
        redisCache.listRightPushAll(key, Arrays.asList(postDtoList.toArray()), time);
    }


    public int getIndex(PostDto postDto, List<PostDto> postDtoList) {
        int index = -1;
        for (int i = 0; i < postDtoList.size(); i++) {
            if (postDtoList.get(i).getId().equals(postDto.getId())) {
                index = i;
                break;
            }
        }
        return index;
    }

    /**
     * 异步更新地区版块数据
     *
     * @param region
     * @param section
     */
    @Async
    public void addRedisSectionPostList(Region region, Section section) {
        Post queryPost = new Post();
        queryPost.setRegionId(region.getId());
        queryPost.setSectionId(section.getId());
        IPage<PostDto> postDtoIPage = postFullService.selectPostFullDto(0, Integer.MAX_VALUE, queryPost);
        if (!redisCache.hasKey(LoadData.POST_CODE + region.getCode() + "_" + section.getCode())) {
            if (!postDtoIPage.getRecords().isEmpty()) {
                redisCache.listRightPushAll(LoadData.POST_CODE + region.getCode() + "_" + section.getCode(),
                        Arrays.asList(postDtoIPage.getRecords().toArray()), LoadData.POST_SECTION_TIME);
            }
        }
    }

    /**
     * 异步更新地区数据
     *
     * @param region
     */
    @Async
    public void addRedisRegionPostList(Region region) {
        Post queryPost = new Post();
        queryPost.setRegionId(region.getId());
        IPage<PostDto> postDtoIPage = postFullService.selectPostFullDto(0, Integer.MAX_VALUE, queryPost);
        if (!redisCache.hasKey(LoadData.POST_CODE + region.getCode())) {
            if (!postDtoIPage.getRecords().isEmpty()) {
                redisCache.listRightPushAll(LoadData.POST_CODE + region.getCode(),
                        Arrays.asList(postDtoIPage.getRecords().toArray()), LoadData.POST_TIME);
            }
        }
    }


    public List<?> getRedisRankPost(Integer current, Integer size) {
        return redisCache.lGet(LoadData.POST_RANK_CODE, setStar(current, size), setEnd(current, size));
    }

    public List<?> getRedisRegionPost(Integer current, Integer size, String regionCode) {
        return redisCache.lGet(LoadData.POST_CODE + regionCode, setStar(current, size), setEnd(current, size));
    }

    public List<?> getRedisSectionPost(Integer current, Integer size, String regionCode, String sectionCode) {
        if (StringUtils.isNotEmpty(regionCode) && StringUtils.isNotEmpty(sectionCode)) {
            return redisCache.lGet(LoadData.POST_CODE + regionCode + "_" + sectionCode,
                    setStar(current, size), setEnd(current, size));
        }
        return redisCache.lGet(LoadData.POST_CODE + regionCode, setStar(current, size), setEnd(current, size));
    }

    public List<?> getRedisSectionPost(Integer current, Integer size, String key) {
        return redisCache.lGet(LoadData.POST_CODE + key, setStar(current, size), setEnd(current, size));
    }


    private Integer setStar(Integer current, Integer size) {
        int start = 0;
        if (current > 1) {
            start = current * size - size;
        }
        return start;
    }

    private Integer setEnd(Integer current, Integer size) {
        return current * size - 1;
    }

}
